#include "CellCoordinate.h"

#include "CatanClassContractException.h"
#include "CatanImpossibleException.h"

namespace catan
{

/*static*/ bool CellCoordinate::canInit(CoordinateX coordinateX, CoordinateY coordinateY)
{
	int xPlusY = coordinateX.getEnum() + coordinateY.getEnum();
	return !((xPlusY < 3) || (xPlusY > 9));
}

CellCoordinate::CellCoordinate(CoordinateX coordinateX, CoordinateY coordinateY) : BaseCoordinate(coordinateX, coordinateY)
{
	if (!CellCoordinate::canInit(coordinateX, coordinateY))
	{
		throw CatanClassContractException(__FILE__, __LINE__, "CellCoordinate::canInit(...) with constructor arguments should be true before creating instance.");
	}
}

bool CellCoordinate::canCreateNeighbor(const VerticalCardinal verticalCardinal) const
{
	if (coordinateX.canCreateNeighbor(verticalCardinal) && coordinateY.canCreateNeighbor(verticalCardinal))
	{
		CoordinateX newX = coordinateX.createNeighbor(verticalCardinal);
		CoordinateY newY = coordinateY.createNeighbor(verticalCardinal);
		if (CellCoordinate::canInit(newX, newY))
		{
			return true;
		}
	}
	return false;
}

CellCoordinate CellCoordinate::createNeighbor(const VerticalCardinal verticalCardinal) const
{
	if (!CellCoordinate::canCreateNeighbor(verticalCardinal))
	{
		throw CatanClassContractException(__FILE__, __LINE__, "<cellCoordinate>.canCreateNeighbor(...) should be true before using <cellCoordinate>.createNeighbor(...).");
	}
	CoordinateX newCoordinateX = coordinateX.createNeighbor(verticalCardinal);
	CoordinateY newCoordinateY = coordinateY.createNeighbor(verticalCardinal);
	return CellCoordinate(newCoordinateX, newCoordinateY);
}

bool CellCoordinate::isOnGameMapEdge(HorizontalCardinal horizontalCardinal) const
{
	switch (horizontalCardinal.getEnum())
	{
	case HorizontalCardinal::HORIZONTAL_CR:
		return coordinateX == catan::x6;
	case HorizontalCardinal::HORIZONTAL_TR:
		return coordinateY == catan::y0;
	case HorizontalCardinal::HORIZONTAL_TL:
		return coordinateX.getEnum() + coordinateY.getEnum() == 3;
	case HorizontalCardinal::HORIZONTAL_CL:
		return coordinateX == catan::x0;
	case HorizontalCardinal::HORIZONTAL_BL:
		return coordinateY == catan::y6;
	case HorizontalCardinal::HORIZONTAL_BR:
		return coordinateX.getEnum() + coordinateY.getEnum() == 9;
	default:
		throw CatanImpossibleException(__FILE__, __LINE__, "Unexpected exception. It should be impossible to create a CellCoordinate with an invalid enum value.");
	}
}

bool CellCoordinate::operator==(const CellCoordinate &other) const
{
	return (coordinateX == other.coordinateX && coordinateY == other.coordinateY);
}

bool CellCoordinate::operator<(const CellCoordinate &other) const
{
	return (
			(coordinateY < other.coordinateY || (coordinateY == other.coordinateY &&
					(coordinateX < other.coordinateX)
			))
	       );
}

CellCoordinate& CellCoordinate::operator=(const CellCoordinate& other)
{
    if (this != &other)
    {
        coordinateX = other.coordinateX;
        coordinateY = other.coordinateY;
    }
    return *this;	
}

}
